(use-modules
 ;; SRFI 64 for unit testing facilities
 (srfi srfi-64)
 ;; utils - the code to be tested
 ((grid-printer) #:prefix grid:))


(test-begin "grid-printer-test")


(test-group
 "col-content-width"

 (test-equal "col-content-width-1"
   6
   (grid:col-content-width 4
                           (grid:make-grid-config
                            #|col-sep|#
                            "|"
                            #|row-sep|#
                            "-"
                            #|intersection|#
                            "+"
                            #|empty|#
                            " "
                            #|col-pad|#
                            1
                            #|row-pad|#
                            1
                            #|pad-direction|#
                            'left))))


(test-group
 "find-longest-string-length*"

 (test-equal "find-longest-string-length*-1"
   3
   (grid:find-longest-string-length* '("b"
                                       "aa"
                                       "c"
                                       "aaa"
                                       "d"))))


(test-group
 "print-segmented-line"

 (test-equal "print-segmented-line-1"
   "|  |  |  |\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-segmented-line 3 2 " " "|" string-port))))

 (test-equal "print-segmented-line-2 - can make zero width segments"
   "|||||\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-segmented-line 4 0 " " "|" string-port))))

 (test-equal "print-segmented-line-3 - can print with non-default characters"
   "-@-@-@-@-@-\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-segmented-line 5 1 "@" "-" string-port))))

 (test-equal "print-segmented-line-4 - works with equal characters"
   "|||||||||||\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-segmented-line 5 1 "|" "|" string-port))))

 (test-equal "print-segmented-line-5 - works with equal characters"
   (string-append
    ;; 5 for the 5 segments
    "|||||"
    ;; 5 for the 5 segments -> width 2
    "|||||"
    ;; 6 for separators
    "||||||"
    ;; final newline
    "\n")
   (call-with-output-string
     (lambda (string-port)
       (grid:print-segmented-line 5 2 "|" "|" string-port))))

 (test-equal "print-segmented-line-6 - negative number of segments -> empty string"
   "|\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-segmented-line -1 2 " " "|" string-port)))))


(test-group
 "col-content-width"
 (test-equal "col-content-width-1"
   9
   (grid:col-content-width 5 (grid:make-grid-config "|" "-" "+" "@" 2 1 'right)))
 (test-equal "col-content-width-2"
   4
   (grid:col-content-width 2 (grid:make-grid-config "|" "-" "+" "@" 1 1 'right)))
 (test-equal "col-content-width-3"
   13
   (grid:col-content-width 5 (grid:make-grid-config "|" "--" "+" "@@" 2 1 'left)))
 (test-equal "col-content-width-3"
   13
   (grid:col-content-width 5 (grid:make-grid-config "|" "--" "+" "@" 2 1 'left)))
 (test-equal "col-content-width-3"
   13
   (grid:col-content-width 5 (grid:make-grid-config "|" "--" "+" " " 2 1 'left))))


(test-group
 "print-empty-line"
 (test-equal "print-empty-line-1"
   "|@@@@|@@@@|@@@@|\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-empty-line
        #|fields|#
        3
        #|data content width|#
        2
        #|grid config|#
        (grid:make-grid-config "|" "-" "+" "@" 1 1 'left)
        #|output port|#
        string-port))))
 (test-equal "print-empty-line-2"
   "|@@@@@@|@@@@@@|@@@@@@|\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-empty-line
        #|fields|#
        3
        #|data content width|#
        2
        #|grid config|#
        (grid:make-grid-config "|" "-" "+" "@" 2 1 'left)
        #|output port|#
        string-port)))))


(test-group
 "print-content-line"
 (test-equal "print-content-line-1"
   "| 1  | 22 |    |\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-content-line
        #|minimum field count|#
        3
        #|field contents|#
        '("1" "22")
        2
        #|grid config|#
        (grid:make-grid-config "|" "-" "+" " " 1 1 'right)
        #|output port|#
        string-port))))
 (test-equal "print-content-line-2"
   "|  1 | 22 |    |\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-content-line
        #|minimum field count|#
        3
        #|field contents|#
        '("1" "22")
        2
        #|grid config|#
        (grid:make-grid-config "|" "-" "+" " " 1 1 'left)
        #|output port|#
        string-port)))))


(test-group
 "print-separating-line"
 (test-equal "print-separating-line-1"
   "+---+---+---+---+\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-separating-line
        #|fields count|#
        4
        #|data content width|#
        1
        #|grid config|#
        (grid:make-grid-config "|" "-" "+" " " 1 1 'right)
        #|output port|#
        string-port))))
 (test-equal "print-separating-line-2"
   "+----+----+----+----+\n"
   (call-with-output-string
     (lambda (string-port)
       (grid:print-separating-line
        #|fields count|#
        4
        #|data content width|#
        2
        #|grid config|#
        (grid:make-grid-config "|" "-" "+" " " 1 1 'right)
        #|output port|#
        string-port)))))


;; not testing output-padding-line as it is only an alias to print-empty-line


(test-group
 "get-nth-cell-parts"
 (test-equal "get-nth-cell-parts-1"
   '("b" "e" "h")
   (grid:get-nth-cell-parts
    '(("a" "b" "c")
      ("d" "e" "f")
      ("g" "h" "i"))
    1))
 (test-equal "get-nth-cell-parts-2"
   '("a" "d" "g")
   (grid:get-nth-cell-parts
    '(("a" "b" "c")
      ("d" "e" "f")
      ("g" "h" "i"))
    0)))


(test-group
 "equalize-lines-count-test"
 (let ([empty " "])
   (test-equal `(("1" "2" "3") ("a" ,empty ,empty) ("x" "y" ,empty))
     (grid:equalize-lines-count '(("1" "2" "3") ("a") ("x" "y")) empty))
   (test-equal `(("a" ,empty ,empty) ("1" "2" "3") ("x" "y" ,empty))
     (grid:equalize-lines-count '(("a") ("1" "2" "3") ("x" "y")) empty))
   (test-equal `(("a" ,empty ,empty) ("x" "y" ,empty) ("1" "2" "3"))
     (grid:equalize-lines-count '(("a") ("x" "y") ("1" "2" "3")) empty))))


(test-group
 "print-grid-row"
 (test-equal "print-grid-row-1"
   (string-append
    "| a | d | g |\n"
    "| b | e | h |\n"
    "| c | f | i |\n")
   (call-with-output-string
     (lambda (string-port)
       (grid:print-grid-row
        #|row data|#
        ;; grid row contains 3 cells
        '(
          ;; cell contains "a" on one line, "b" on one line, "c" on one line
          ("a" "b" "c")
          ("d" "e" "f")
          ("g" "h" "i"))
        #|fields count|#
        3
        #|data content width|#
        1
        #|grid configuration|#
        (grid:make-grid-config "|" "-" "+" " " 1 0 'right)
        #|output port|#
        string-port)))))


(test-group
 "print-grid"
 (test-equal "print-grid-1"
   (string-append
    "+---+---+---+\n"
    "| a | d | g |\n"
    "| b | e | h |\n"
    "| c | f | i |\n"
    "+---+---+---+\n"
    "| 1 | 4 | 7 |\n"
    "| 2 | 5 | 8 |\n"
    "| 3 | 6 | 9 |\n"
    "+---+---+---+\n")
   (call-with-output-string
     (lambda (string-port)
       (grid:print-grid
        ;; grid containing 2 rows
        '(
          ;; grid row contains 3 cells
          (
           ;; cell contains "a" on one line, "b" on one line, "c" on one line
           ("a" "b" "c")
           ("d" "e" "f")
           ("g" "h" "i"))
          (("1" "2" "3")
           ("4" "5" "6")
           ("7" "8" "9")))
        string-port
        #:grid-config (grid:make-grid-config "|" "-" "+" " " 1 0 'right)))))


 (test-equal "print-grid-2"
   (string-append
    "+---+---+\n"
    "| a |   |\n"
    "| b |   |\n"
    "| c |   |\n"
    "+---+---+\n")
   (call-with-output-string
     (lambda (string-port)
       (grid:print-grid
        ;; grid
        '(
          ;; row
          (
           ;; col 1
           ("a" "b" "c")
           ;; col 2
           ("")))
        string-port
        #:grid-config (grid:make-grid-config "|" "-" "+" " " 1 0 'right)))))


 ;; (test-equal "print-grid--grid-in-grid-1"
 ;;   (string-append
 ;;    "+-------+-------+\n"
 ;;    "| +---+ |       |\n"
 ;;    "| | a | |       |\n"
 ;;    "| +---+ |       |\n"
 ;;    "+-------+-------+\n")
 ;;   (let ([inner-grid
 ;;          (call-with-output-string
 ;;            (lambda (string-port)
 ;;              (grid:print-grid
 ;;               '((("a")))
 ;;               string-port
 ;;               #:grid-config (grid:make-grid-config "|" "-" "+" " " 1 0 'right))))])
 ;;     (call-with-output-string
 ;;       (lambda (string-port)
 ;;         (let ([inner-grid-as-list
 ;;                (string-split (string-trim-right inner-grid)
 ;;                              (λ (char) (char=? char #\newline)))])

 ;;           (display (simple-format #f "list inner grid: ~a\n" inner-grid-as-list))
 ;;           (display (simple-format #f "length: ~a\n" (length inner-grid-as-list)))

 ;;           (grid:print-grid
 ;;            ;; grid
 ;;            `(
 ;;              ;; row
 ;;              (
 ;;               ;; col 1
 ;;               ,inner-grid-as-list
 ;;               ;; col 2
 ;;               ("")))
 ;;            string-port
 ;;            #:grid-config (grid:make-grid-config "|" "-" "+" " " 1 0 'right)))))))


 ;; (test-equal "print-grid--grid-in-grid-2"
 ;;   (string-append
 ;;    "+---------------+---------------+\n"
 ;;    "| +---+---+---+ |               |\n"
 ;;    "| | a | d | g | |               |\n"
 ;;    "| | b | e | h | |               |\n"
 ;;    "| | c | f | i | |               |\n"
 ;;    "| +---+---+---+ |               |\n"
 ;;    "| | 1 | 4 | 7 | |               |\n"
 ;;    "| | 2 | 5 | 8 | |               |\n"
 ;;    "| | 3 | 6 | 9 | |               |\n"
 ;;    "| +---+---+---+ |               |\n"
 ;;    "+---------------+---------------+\n")
 ;;   (let ([inner-grid
 ;;          (call-with-output-string
 ;;            (lambda (string-port)
 ;;              (grid:print-grid
 ;;               ;; grid containing 2 rows
 ;;               '(
 ;;                 ;; grid row contains 3 cells
 ;;                 (
 ;;                  ;; cell contains "a" on one line, "b" on one line, "c" on one line
 ;;                  ("a" "b" "c")
 ;;                  ("d" "e" "f")
 ;;                  ("g" "h" "i"))
 ;;                 (("1" "2" "3")
 ;;                  ("4" "5" "6")
 ;;                  ("7" "8" "9")))
 ;;               string-port
 ;;               #:grid-config (grid:make-grid-config "|" "-" "+" " " 1 0 'right))))])
 ;;     (call-with-output-string
 ;;       (lambda (string-port)
 ;;         (display (simple-format #f "~a\n" (string-trim-right inner-grid)))
 ;;         (grid:print-grid
 ;;          ;; grid containing 1 row
 ;;          `(
 ;;            ;; the 1 row
 ;;            (
 ;;             ;; the 2 cells
 ;;             ,(string-split (string-trim-right inner-grid)
 ;;                            (λ (char) (char=? char #\newline)))
 ;;             ("")))
 ;;          string-port
 ;;          #:grid-config (grid:make-grid-config "|" "-" "+" " " 1 0 'right))))))
 )


(test-end "grid-printer-test")
